home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / uae-0.000 / uae-0 / uae-0.6.0 / cia.c < prev    next >
C/C++ Source or Header  |  1996-06-17  |  16KB  |  729 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * CIA chip support
  5.   *
  6.   * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
  7.   * Copyright 1996 Stefan Reinauer
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12. #include <assert.h>
  13.  
  14. #include "config.h"
  15. #include "options.h"
  16. #include "events.h"
  17. #include "memory.h"
  18. #include "custom.h"
  19. #include "cia.h"
  20. #include "disk.h"
  21. #include "xwin.h"
  22. #include "keybuf.h"
  23. #include "gui.h"
  24.  
  25. #define DIV10 5 /* Yes, a bad identifier. */
  26.  
  27. /* battclock stuff */
  28. #define RTC_D_ADJ      8
  29. #define RTC_D_IRQ      4
  30. #define RTC_D_BUSY     2
  31. #define RTC_D_HOLD     1
  32. #define RTC_E_t1       8
  33. #define RTC_E_t0       4
  34. #define RTC_E_INTR     2
  35. #define RTC_E_MASK     1
  36. #define RTC_F_TEST     8
  37. #define RTC_F_24_12    4
  38. #define RTC_F_STOP     2
  39. #define RTC_F_RSET     1
  40.  
  41. static UBYTE clock_control_d = RTC_D_ADJ + RTC_D_HOLD;
  42. static UBYTE clock_control_e = 0;
  43. static UBYTE clock_control_f = RTC_F_24_12;
  44.  
  45. static UBYTE ciaaicr,ciaaimask,ciabicr,ciabimask;
  46. static UBYTE ciaacra,ciaacrb,ciabcra,ciabcrb;
  47. static ULONG ciaata,ciaatb,ciabta,ciabtb;
  48. static UWORD ciaala,ciaalb,ciabla,ciablb;
  49. static ULONG ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
  50. static int ciaatodon, ciabtodon;
  51. static int ciaatlatch,ciabtlatch;
  52. static UBYTE ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr;
  53. static UBYTE ciabpra,ciabprb,ciabdra,ciabdrb,ciabsdr; 
  54. static int div10;
  55. static int kbstate, kback;
  56.  
  57. static int prtopen;
  58. static FILE *prttmp;
  59.  
  60. static void setclr(UBYTE *p, UBYTE val)
  61. {
  62.     if (val & 0x80) {
  63.     *p |= val & 0x7F;
  64.     } else {
  65.     *p &= ~val;
  66.     }
  67. }
  68.  
  69. static void RethinkICRA(void)
  70. {
  71.     if (ciaaimask & ciaaicr) {
  72.     ciaaicr |= 0x80;
  73.     custom_bank.wput(0xDFF09C,0x8008);
  74.     } else {
  75.     ciaaicr &= 0x7F;
  76. /*    custom_bank.wput(0xDFF09C,0x0008);*/
  77.     }
  78. }
  79.  
  80. static void RethinkICRB(void)
  81. {
  82.     if (ciabicr & 0x10) {
  83.     custom_bank.wput(0xDFF09C,0x9000);
  84.     }
  85.     if (ciabimask & ciabicr) {
  86.     ciabicr |= 0x80;
  87.     custom_bank.wput(0xDFF09C,0xA000);
  88.     } else {
  89.     ciabicr &= 0x7F;
  90. /*    custom_bank.wput(0xDFF09C,0x2000);*/
  91.     }
  92. }
  93.  
  94. static int lastdiv10;
  95.  
  96. static void CIA_update(void)
  97. {
  98.     unsigned long int ccount = cycles - eventtab[ev_cia].oldcycles + lastdiv10;
  99.     unsigned long int ciaclocks = ccount / DIV10;
  100.  
  101.     int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
  102.  
  103.     lastdiv10 = div10;
  104.     div10 = ccount % DIV10;
  105.     
  106.     /* CIA A timers */
  107.     if ((ciaacra & 0x21) == 0x01) {
  108.     assert((ciaata+1) >= ciaclocks);
  109.     if ((ciaata+1) == ciaclocks) {
  110.         aovfla = 1;
  111.         if ((ciaacrb & 0x61) == 0x41) {
  112.         if (ciaatb-- == 0) aovflb = 1;        
  113.         }
  114.     }         
  115.     ciaata -= ciaclocks;
  116.     }
  117.     if ((ciaacrb & 0x61) == 0x01) {
  118.     assert((ciaatb+1) >= ciaclocks);
  119.     if ((ciaatb+1) == ciaclocks) aovflb = 1;
  120.     ciaatb -= ciaclocks;
  121.     }
  122.     
  123.     /* CIA B timers */
  124.     if ((ciabcra & 0x21) == 0x01) {
  125.     assert((ciabta+1) >= ciaclocks);
  126.     if ((ciabta+1) == ciaclocks) {
  127.         bovfla = 1;
  128.         if ((ciabcrb & 0x61) == 0x41) {
  129.         if (ciabtb-- == 0) bovflb = 1;
  130.         }
  131.     } 
  132.     ciabta -= ciaclocks;
  133.     }
  134.     if ((ciabcrb & 0x61) == 0x01) {
  135.     assert ((ciabtb+1) >= ciaclocks);
  136.     if ((ciabtb+1) == ciaclocks) bovflb = 1;
  137.     ciabtb -= ciaclocks;
  138.     }
  139.     if (aovfla) {
  140.     ciaaicr |= 1; RethinkICRA();
  141.     ciaata = ciaala;
  142.     if (ciaacra & 0x8) ciaacra &= ~1;
  143.     }
  144.     if (aovflb) {
  145.     ciaaicr |= 2; RethinkICRA();
  146.     ciaatb = ciaalb;
  147.     if (ciaacrb & 0x8) ciaacrb &= ~1;
  148.     }
  149.     if (bovfla) {
  150.     ciabicr |= 1; RethinkICRB();
  151.     ciabta = ciabla;
  152.     if (ciabcra & 0x8) ciabcra &= ~1;
  153.     }
  154.     if (bovflb) {
  155.     ciabicr |= 2; RethinkICRB();
  156.     ciabtb = ciablb;
  157.     if (ciabcrb & 0x8) ciabcrb &= ~1;
  158.     }
  159. }
  160.  
  161. static void CIA_calctimers(void)
  162. {
  163.     int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
  164.  
  165.     eventtab[ev_cia].oldcycles = cycles;
  166.     
  167.     if ((ciaacra & 0x21) == 0x01) {
  168.     ciaatimea = (DIV10-div10) + DIV10*ciaata;    
  169.     }
  170.     if ((ciaacrb & 0x61) == 0x41) {
  171.     /* Timer B will not get any pulses if Timer A is off. */
  172.     if (ciaatimea >= 0) {
  173.         /* If Timer A is in one-shot mode, and Timer B needs more than
  174.          * one pulse, it will not underflow. */
  175.         if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
  176.         /* Otherwise, we can determine the time of the underflow. */
  177.         ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
  178.         }
  179.     }
  180.     }
  181.     if ((ciaacrb & 0x61) == 0x01) {
  182.     ciaatimeb = (DIV10-div10) + DIV10*ciaatb;
  183.     }
  184.  
  185.     if ((ciabcra & 0x21) == 0x01) {
  186.     ciabtimea = (DIV10-div10) + DIV10*ciabta;    
  187.     }
  188.     if ((ciabcrb & 0x61) == 0x41) {
  189.     /* Timer B will not get any pulses if Timer A is off. */
  190.     if (ciabtimea >= 0) {
  191.         /* If Timer A is in one-shot mode, and Timer B needs more than
  192.          * one pulse, it will not underflow. */
  193.         if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
  194.         /* Otherwise, we can determine the time of the underflow. */
  195.         ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
  196.         }
  197.     }
  198.     }
  199.     if ((ciabcrb & 0x61) == 0x01) {
  200.     ciabtimeb = (DIV10-div10) + DIV10*ciabtb;
  201.     }
  202.     eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
  203.                    || ciabtimea != -1 || ciabtimeb != -1);
  204.     if (eventtab[ev_cia].active) {
  205.     unsigned long int ciatime = ~0L;
  206.     if (ciaatimea != -1) ciatime = ciaatimea;
  207.     if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
  208.     if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
  209.     if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
  210.     eventtab[ev_cia].evtime = ciatime;
  211.     }
  212.     events_schedule();
  213. }
  214.  
  215. void CIA_handler(void)
  216. {
  217.     CIA_update();
  218.     CIA_calctimers();
  219. }
  220.  
  221. void CIA_hsync_handler(void)
  222. {
  223.     static int keytime = 0;
  224.  
  225.     if (ciabtodon)
  226.     ciabtod++;
  227.     ciabtod &= 0xFFFFFF;
  228. #if 1
  229.     if (indexpulse == 0){
  230.     ciabicr |= 0x10;
  231.     RethinkICRB();
  232. /*    if (dskdmaen != 2)
  233.         DISK_Index();*/
  234.     indexpulse = 30; /* whatever */
  235.     } else {
  236.     indexpulse--;
  237.     }
  238. #endif
  239.     if (ciabtod == ciabalarm) {
  240.     ciabicr |= 4; RethinkICRB();
  241.     }
  242.     if (keys_available() && kback && (++keytime & 15) == 0) {
  243.     switch(kbstate) {
  244.      case 0:
  245.         ciaasdr = (BYTE)~0xFB; /* aaarghh... stupid compiler */
  246.         kbstate++;
  247.         break;
  248.      case 1:
  249.         kbstate++;
  250.         ciaasdr = (BYTE)~0xFD;
  251.         break;
  252.      case 2:
  253.         ciaasdr = ~get_next_key();
  254.         break;
  255.     }
  256.     ciaaicr |= 8; RethinkICRA();
  257.     }
  258. }
  259.  
  260. void CIA_vsync_handler()
  261. {    
  262.     if (ciaatodon) 
  263.     ciaatod++;
  264.     ciaatod &= 0xFFFFFF;
  265.     if (ciaatod == ciaaalarm) {
  266.     ciaaicr |= 4; RethinkICRA();
  267.     }
  268. }
  269.  
  270. static UBYTE ReadCIAA(UWORD addr)
  271. {
  272.     UBYTE tmp;
  273.     
  274.     switch(addr & 0xf){
  275.      case 0: 
  276.     tmp = (DISK_status() & 0x3C);
  277.     if (!buttonstate[0]) tmp |= 0x40;
  278.     if (!joy0button) tmp |= 0x80;
  279.     return tmp;
  280.      case 1:
  281.     return ciaaprb;
  282.      case 2:
  283.     return ciaadra;
  284.      case 3:
  285.     return ciaadrb;
  286.      case 4:
  287.     return ciaata & 0xff;
  288.      case 5:
  289.     return ciaata >> 8;
  290.      case 6:
  291.     return ciaatb & 0xff;
  292.      case 7:
  293.     return ciaatb >> 8;
  294.      case 8:
  295.     if (ciaatlatch) {
  296.         ciaatlatch = 0;
  297.         return ciaatol & 0xff;
  298.     } else return ciaatod & 0xff;
  299.      case 9:
  300.     if (ciaatlatch) return (ciaatol >> 8) & 0xff;
  301.     else return (ciaatod >> 8) & 0xff;
  302.      case 10:
  303.     ciaatlatch = 1; ciaatol = ciaatod; /* ??? only if not already latched? */
  304.     return (ciaatol >> 16) & 0xff;
  305.      case 12:
  306.     return ciaasdr;
  307.      case 13:
  308.     tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
  309.      case 14:
  310.     return ciaacra;
  311.      case 15:
  312.     return ciaacrb;
  313.     }
  314.     return 0;
  315. }
  316.  
  317. static UBYTE ReadCIAB(UWORD addr)
  318. {
  319.     UBYTE tmp;
  320.     
  321.     switch(addr & 0xf){
  322.      case 0: 
  323.     return ciabpra;
  324.      case 1:
  325.     return ciabprb;
  326.      case 2:
  327.     return ciabdra;
  328.      case 3:
  329.     return ciabdrb;
  330.      case 4:
  331.     return ciabta & 0xff;
  332.      case 5:
  333.     return ciabta >> 8;
  334.      case 6:
  335.     return ciabtb & 0xff;
  336.      case 7:
  337.     return ciabtb >> 8;
  338.      case 8:
  339.     if (ciabtlatch) {
  340.         ciabtlatch = 0;
  341.         return ciabtol & 0xff;
  342.     } else return ciabtod & 0xff;
  343.      case 9:
  344.     if (ciabtlatch) return (ciabtol >> 8) & 0xff;
  345.     else return (ciabtod >> 8) & 0xff;
  346.      case 10:
  347.     ciabtlatch = 1; ciabtol = ciabtod;
  348.     return (ciabtol >> 16) & 0xff;
  349.      case 12:
  350.     return ciabsdr;
  351.      case 13:
  352.     tmp = ciabicr; ciabicr = 0; RethinkICRB();
  353.     return tmp;
  354.      case 14:
  355.     return ciabcra;
  356.      case 15:
  357.     return ciabcrb;
  358.     }
  359.     return 0;
  360. }
  361.  
  362. static void WriteCIAA(UWORD addr,UBYTE val)
  363. {
  364.     int oldled;
  365.     switch(addr & 0xf){
  366.      case 0:
  367.     oldled = ciaapra & 2;
  368.     ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2);
  369.     if ((ciaapra & 2) != oldled)
  370.         gui_led (0, !(ciaapra & 2));
  371.     break;
  372.      case 1:
  373.     ciaaprb = val;
  374.     if (prtopen==1) {
  375.         fprintf (prttmp,"%c",val);
  376.         if (val==0x04) {
  377. #if defined(__unix) && !defined(__bebox__) && !defined(__DOS__)
  378.         pclose (prttmp);
  379. #else
  380.         fclose (prttmp);
  381. #endif
  382.         prtopen = 0;
  383.         }
  384.         } else {
  385. #if defined(__unix) && !defined(__bebox__) && !defined(__DOS__)
  386.             prttmp=(FILE *)popen ((char *)prtname,"w");
  387. #else
  388.             prttmp=(FILE *)fopen ((char *)prtname,"wb");
  389. #endif
  390.         if (prttmp != NULL) {
  391.         prtopen = 1;
  392.         fprintf (prttmp,"%c",val);
  393.         }
  394.         }
  395.     ciaaicr |= 0x10;
  396.     break;
  397.      case 2:
  398.     ciaadra = val; break;
  399.      case 3:
  400.     ciaadrb = val; break;
  401.      case 4:
  402.     CIA_update();
  403.     ciaala = (ciaala & 0xff00) | val;
  404.     CIA_calctimers();
  405.     break;
  406.      case 5:
  407.     CIA_update();
  408.     ciaala = (ciaala & 0xff) | (val << 8);
  409.     if ((ciaacra & 1) == 0)
  410.         ciaata = ciaala;
  411.     if (ciaacra & 8) { 
  412.         ciaata = ciaala; 
  413.         ciaacra |= 1; 
  414.     }
  415.     CIA_calctimers();
  416.     break;
  417.      case 6:
  418.     CIA_update();
  419.     ciaalb = (ciaalb & 0xff00) | val;
  420.     CIA_calctimers();
  421.     break;
  422.      case 7:
  423.     CIA_update();
  424.     ciaalb = (ciaalb & 0xff) | (val << 8);
  425.     if ((ciaacrb & 1) == 0)
  426.         ciaatb = ciaalb;
  427.     if (ciaacrb & 8) { 
  428.         ciaatb = ciaalb;
  429.         ciaacrb |= 1; 
  430.     }
  431.     CIA_calctimers();
  432.     break;
  433.      case 8:
  434.     if (ciaacrb & 0x80){
  435.         ciaaalarm = (ciaaalarm & ~0xff) | val;
  436.     } else {
  437.         ciaatod = (ciaatod & ~0xff) | val;
  438.         ciaatodon = 1;
  439.     }
  440.     break;
  441.      case 9:
  442.     if (ciaacrb & 0x80){
  443.         ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
  444.     } else {
  445.         ciaatod = (ciaatod & ~0xff00) | (val << 8);
  446.         ciaatodon = 0;
  447.     }
  448.     break;
  449.      case 10:
  450.     if (ciaacrb & 0x80){
  451.         ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
  452.     } else {
  453.         ciaatod = (ciaatod & ~0xff0000) | (val << 16);
  454.         ciaatodon = 0;
  455.     }
  456.     break;
  457.      case 12:
  458.     ciaasdr = val; break;
  459.      case 13:
  460.     setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
  461.      case 14:
  462.     CIA_update();
  463.     ciaacra = val;
  464.     if (ciaacra & 0x10){
  465.         ciaacra &= ~0x10;
  466.         ciaata = ciaala;
  467.     }
  468.     if (ciaacra & 0x40) {
  469.         kback = 1;
  470.     }
  471.     CIA_calctimers();
  472.     break;
  473.      case 15:
  474.     CIA_update();
  475.     ciaacrb = val; 
  476.     if (ciaacrb & 0x10){
  477.         ciaacrb &= ~0x10;
  478.         ciaatb = ciaalb;
  479.     }
  480.     CIA_calctimers();
  481.     break;
  482.     }
  483. }
  484.  
  485. static void WriteCIAB(UWORD addr,UBYTE val)
  486. {
  487.     switch(addr & 0xf){
  488.      case 0:
  489.     ciabpra = (ciabpra & ~0x3) | (val & 0x3); break;
  490.      case 1:
  491.     ciabprb = val; DISK_select(val); break;
  492.      case 2:
  493.     ciabdra = val; break;
  494.      case 3:
  495.     ciabdrb = val; break;
  496.      case 4:
  497.     CIA_update();
  498.     ciabla = (ciabla & 0xff00) | val;
  499.     CIA_calctimers();
  500.     break;
  501.      case 5:
  502.     CIA_update();
  503.     ciabla = (ciabla & 0xff) | (val << 8);
  504.     if ((ciabcra & 1) == 0) 
  505.         ciabta = ciabla;
  506.     if (ciabcra & 8) {
  507.         ciabta = ciabla; 
  508.         ciabcra |= 1; 
  509.     } 
  510.     CIA_calctimers();
  511.     break;
  512.      case 6:
  513.     CIA_update();
  514.     ciablb = (ciablb & 0xff00) | val;
  515.     CIA_calctimers();
  516.     break;
  517.      case 7:
  518.     CIA_update();
  519.     ciablb = (ciablb & 0xff) | (val << 8);
  520.     if ((ciabcrb & 1) == 0)
  521.         ciabtb = ciablb;
  522.     if (ciabcrb & 8) {
  523.         ciabtb = ciablb;
  524.         ciabcrb |= 1;
  525.     }
  526.     CIA_calctimers();
  527.     break;
  528.      case 8:
  529.     if (ciabcrb & 0x80){
  530.         ciabalarm = (ciabalarm & ~0xff) | val;
  531.     } else {
  532.         ciabtod = (ciabtod & ~0xff) | val;
  533.         ciabtodon = 1;
  534.     }
  535.     break;
  536.      case 9:
  537.     if (ciabcrb & 0x80){
  538.         ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
  539.     } else {
  540.         ciabtod = (ciabtod & ~0xff00) | (val << 8);
  541.         ciabtodon = 0;
  542.     }
  543.     break;
  544.      case 10:
  545.     if (ciabcrb & 0x80){
  546.         ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
  547.     } else {
  548.         ciabtod = (ciabtod & ~0xff0000) | (val << 16);
  549.         ciabtodon = 0;
  550.     }
  551.     break;
  552.      case 12:
  553.     ciabsdr = val; 
  554.     break;
  555.      case 13:
  556.     setclr(&ciabimask,val); 
  557.     break;
  558.      case 14:
  559.     CIA_update();
  560.     ciabcra = val;
  561.     if (ciabcra & 0x10){
  562.         ciabcra &= ~0x10;
  563.         ciabta = ciabla;
  564.     }
  565.     CIA_calctimers();
  566.     break;
  567.      case 15:
  568.     CIA_update();
  569.     ciabcrb = val; 
  570.     if (ciabcrb & 0x10){
  571.         ciabcrb &= ~0x10;
  572.         ciabtb = ciablb;
  573.     }
  574.     CIA_calctimers();
  575.     break;
  576.     }
  577. }
  578.  
  579. void CIA_reset(void)
  580. {
  581.     kback = 1;
  582.     kbstate = 0;
  583.     
  584.     ciaatlatch = ciabtlatch = 0;
  585.     ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
  586.     ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
  587.     ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
  588.     div10 = 0;
  589.     lastdiv10 = 0;
  590.     CIA_calctimers();
  591.  
  592.     ciabpra = 0x04;
  593. }
  594.  
  595. void dumpcia(void)
  596. {
  597.     printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  598.        (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod, 
  599.        ciaatlatch ? " latched" : "", ciaata, ciaatb);
  600.     printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  601.        (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod, 
  602.        ciabtlatch ? " latched" : "", ciabta, ciabtb);
  603. }
  604.  
  605. /* CIA memory access */
  606.  
  607. static ULONG cia_lget(CPTR) REGPARAM;
  608. static UWORD cia_wget(CPTR) REGPARAM;
  609. static UBYTE cia_bget(CPTR) REGPARAM;
  610. static void  cia_lput(CPTR, ULONG) REGPARAM;
  611. static void  cia_wput(CPTR, UWORD) REGPARAM;
  612. static void  cia_bput(CPTR, UBYTE) REGPARAM;
  613.  
  614. addrbank cia_bank = {
  615.     cia_lget, cia_wget, cia_bget,
  616.     cia_lput, cia_wput, cia_bput,
  617.     default_xlate, default_check
  618. };
  619.  
  620. ULONG cia_lget(CPTR addr)
  621. {
  622.     return cia_bget(addr+3);
  623. }
  624.  
  625. UWORD cia_wget(CPTR addr)
  626. {
  627.     return cia_bget(addr+1);
  628. }
  629.  
  630. UBYTE cia_bget(CPTR addr)
  631. {
  632.     if ((addr & 0x3001) == 0x2001)
  633.         return ReadCIAA((addr & 0xF00) >> 8);
  634.     if ((addr & 0x3001) == 0x1000)
  635.         return ReadCIAB((addr & 0xF00) >> 8);
  636.     return 0;
  637. }
  638.  
  639. void cia_lput(CPTR addr, ULONG value)
  640. {
  641.     cia_bput(addr+3,value); /* FIXME ? */
  642. }
  643.  
  644. void cia_wput(CPTR addr, UWORD value)
  645. {
  646.     cia_bput(addr+1,value);
  647. }
  648.  
  649. void cia_bput(CPTR addr, UBYTE value)
  650. {
  651.     if ((addr & 0x3001) == 0x2001)
  652.         WriteCIAA((addr & 0xF00) >> 8,value);
  653.     if ((addr & 0x3001) == 0x1000)
  654.         WriteCIAB((addr & 0xF00) >> 8,value);
  655. }
  656.  
  657. /* battclock memory access */
  658.  
  659. static ULONG clock_lget(CPTR) REGPARAM;
  660. static UWORD clock_wget(CPTR) REGPARAM;
  661. static UBYTE clock_bget(CPTR) REGPARAM;
  662. static void  clock_lput(CPTR, ULONG) REGPARAM;
  663. static void  clock_wput(CPTR, UWORD) REGPARAM;
  664. static void  clock_bput(CPTR, UBYTE) REGPARAM;
  665.  
  666. addrbank clock_bank = {
  667.     clock_lget, clock_wget, clock_bget,
  668.     clock_lput, clock_wput, clock_bput,
  669.     default_xlate, default_check
  670. };
  671.  
  672. ULONG clock_lget(CPTR addr)
  673. {
  674.     return clock_bget(addr+3);
  675. }
  676.  
  677. UWORD clock_wget(CPTR addr)
  678. {
  679.     return clock_bget(addr+1);
  680. }
  681.  
  682. UBYTE clock_bget(CPTR addr)
  683. {
  684.     time_t t=time(0);
  685.     struct tm *ct;
  686.     ct=localtime(&t);
  687.     switch (addr & 0x3f)
  688.     {
  689.      case 0x03: return ct->tm_sec % 10;
  690.      case 0x07: return ct->tm_sec / 10;
  691.      case 0x0b: return ct->tm_min % 10;
  692.      case 0x0f: return ct->tm_min / 10;
  693.      case 0x13: return ct->tm_hour % 10;
  694.      case 0x17: return ct->tm_hour / 10;
  695.      case 0x1b: return ct->tm_mday % 10;
  696.      case 0x1f: return ct->tm_mday / 10;
  697.      case 0x23: return (ct->tm_mon+1) % 10;
  698.      case 0x27: return (ct->tm_mon+1) / 10;
  699.      case 0x2b: return ct->tm_year % 10;
  700.      case 0x2f: return ct->tm_year / 10;
  701.  
  702.      case 0x33: return ct->tm_wday;  /*Hack by -=SR=- */
  703.      case 0x37: return clock_control_d;
  704.      case 0x3b: return clock_control_e;
  705.      case 0x3f: return clock_control_f;
  706.     }
  707.     return 0;
  708. }
  709.  
  710. void clock_lput(CPTR addr, ULONG value)
  711. {
  712.     /* No way */
  713. }
  714.  
  715. void clock_wput(CPTR addr, UWORD value)
  716. {
  717.     /* No way */
  718. }
  719.  
  720. void clock_bput(CPTR addr, UBYTE value)
  721. {
  722.     switch (addr & 0x3f)
  723.     {
  724.      case 0x37: clock_control_d=value; break;
  725.      case 0x3b: clock_control_e=value; break;
  726.      case 0x3f: clock_control_f=value; break;
  727.     }
  728. }
  729.